#pragma once

#include <cstdint>
#include <cstddef>
#include "Containers/String.h"
#include "Misc/CommonMacros.h"

struct WHENGINE_API STypeID
{
	STypeID()
	{ 
	}

	//用于特化的模版类型
	//例如：TMap<int,bool>
	//InTemplateID: TMap<K,V>
	//InTemplateArgumentTypeIDs: {int,bool}
	//InArgumentNames: {K,V}
	STypeID(
		const STypeID & InTemplateID
		, const TVector<STypeID> & InTemplateArgumentTypeIDs
		, const TVector<CString> & InArgumentNames
		)
	{
		TemplateTypeID=InTemplateID;
		TemplateArgumentTypeIDs=InTemplateArgumentTypeIDs;

		TypeFullName=CreateTemplateTypeName(
			InTemplateID
			,InTemplateArgumentTypeIDs
			,InArgumentNames
			);
		Hash=TypeFullName.GetHashCode();

		//判断是否是c++类型
		bIsNativeType=InTemplateID.bIsNativeType;
		if(bIsNativeType)
		{
			for(auto& TypeID : InTemplateArgumentTypeIDs)
			{
				if(!TypeID.bIsNativeType)
				{
					bIsNativeType=false;
					break;
				}
			}
		}
		
	}

	//仅用于非模板类型
	STypeID(const CString & InTypeFullName,bool InIsNativeType)
	{
		TypeFullName=InTypeFullName;
		Hash=TypeFullName.GetHashCode();
		bIsNativeType=InIsNativeType;
	}

	//仅用于非模板类型
	STypeID(const TVector<CString> & InNameScope, const CString & InTypeName,bool InIsNativeType)
	{
		//create  ,such as Engine.Vector3
		if(InNameScope.Num()>0)
		{
			for(auto& Name : InNameScope)
			{
				TypeFullName+=Name;
				TypeFullName+=U"::";
			}
		}
		TypeFullName+=InTypeName;

		Hash=TypeFullName.GetHashCode();
		bIsNativeType=InIsNativeType;
	}

    static CString CreateTemplateTypeName(
        const STypeID& InGenericTypeName
        ,const TVector<STypeID>& InArgumentTypes
        ,const TVector<CString>& InArgumentPlaceholderNames);
        
    static CString CreateTemplateTypeName(
        const CString& InGenericTypeName
        ,const TVector<CString>& InTypeArguments
        ,const TVector<CString>& InArgumentPlaceholderNames);

	uint64_t GetHashCode() const
	{
		return Hash;
	}

	bool IsValid() const
	{
		return TypeFullName.GetLength()>0;
	}

	bool IsScriptType() const
	{
		return !bIsNativeType;
	}

	bool IsGenerializedType() const
	{
		return TemplateTypeID.HasValue();
	}

	bool operator==(const STypeID& InID) const
	{
		return TypeFullName==InID.TypeFullName;
	}

	CString GetTypeFullName() const
	{
		return TypeFullName;
	}
protected:
	uint64_t Hash=-1;
	CString TypeFullName;

	//是否是c++类型，
	//对于模版类型，只有模板和参数都是c++类型才是c++类型
	bool bIsNativeType=false;

//模板函数相关：

	//模板类型ID
	TOptional<STypeID> TemplateTypeID;
	//模板参数类型ID
	TVector<STypeID> TemplateArgumentTypeIDs;
};